#define _POSIX_SOURCE
#define _BSD_SOURCE

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include "rngs.h"
#include <getopt.h>

#ifndef TEST_CASES
#define TEST_CASES 10000
#endif

#ifndef RAND_NUM
#define RAND_NUM 100
#endif

#ifndef SUPP
#define SUPP 10
#endif

int createGameState(struct gameState *state)
{
	int i, j;

	// Generate 2-4 players
	state->numPlayers = floor(Random() * (MAX_PLAYERS - 1)) + 2;

	for (i = 0; i < state->numPlayers; i++) {
		state->handCount[i] = floor(Random() * RAND_NUM);
		state->deckCount[i] = floor(Random() * RAND_NUM);
		state->discardCount[i] = floor(Random() * RAND_NUM);

		for (j = 0; j < state->handCount[i]; j++) {
			state->hand[i][j] = floor(Random() * (treasure_map + 1));
		}

		for (j = 0; j < state->deckCount[i]; j++) {
			state->deck[i][j] = floor(Random() * (treasure_map + 1));
		}

		for (j = 0; j < state->discardCount[i]; j++) {
			state->discard[i][j] = floor(Random() * (treasure_map + 1));
		}
	}
	
	return 0;
}

int test(struct gameState *state)
{
	int i, j, k, result, count;

	for (i = 0; i < state->numPlayers; i++) {

		for (j = 0; j <= treasure_map; j++) {
			count = 0;

			result = fullDeckCount(i, j, state);

			for (k = 0; k < state->handCount[i]; k++) {
				if (state->hand[i][k] == j) { count++; }
			}

			for (k = 0; k < state->deckCount[i]; k++) {
				if (state->deck[i][k] == j) { count++; }
			}

			for (k = 0; k < state->discardCount[i]; k++) {
				if (state->discard[i][k] == j) { count++; }
			}


			//printf("result: %d, expect: %d\n", result, count);
			if (result != count) {
				return -1;
			}
		}
	}

	return 0;
}

int main(int argc, char **argv)
{
	int i, result;
	struct gameState state;

	for (i = 0; i < TEST_CASES; i++) {
		createGameState(&state);
		result = test(&state);
		if (result == 0) {
			printf("TEST CASE #%d = PASS\n", i + 1);
		} else {
			printf("TEST CASE #%d = FAIL\n", i + 1);
		}
	}

	return 0;
}